package com.booleansoft.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.List;

import sun.misc.BASE64Encoder;


public class FileHelper {
	public static String read(String path,String code) throws Exception{
		BufferedReader fr=null;
		StringBuffer newsb=new StringBuffer();
		try {
			fr=new BufferedReader(
					new InputStreamReader(
							new FileInputStream(path),code));
			
			String line=null;
			while((line=fr.readLine())!=null){
				newsb.append(line);
				newsb.append("\r\n");
			}
		}catch (Exception e) {
			// TODO Auto-generated catch block
			throw e;
		}finally{
			try {
				if(fr!=null){
					fr.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return newsb.toString().replaceFirst("\r\n$", "");
	}
	public static String encodeBase64(InputStream in){
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			BASE64Encoder encoder = new BASE64Encoder();
			encoder.encode(in, bos);
		} catch (Exception e) {
			e.printStackTrace(System.err);
		}
		return bos.toString();
	}
	public static void write(String path,String content,String code) throws Exception{
		BufferedWriter bw=null;
		try {
			bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),code));
			bw.write(content);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw e;
		}finally{
			if(bw!=null){
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		deleteFile(new File("V:\\work\\server\\common"));
//		long d1=System.currentTimeMillis();
//		copy(new File("V:\\work\\code\\mytools\\redirect\\datas\\model\\tomcat-6.0.35_xt"),new File("D:\\temp\\tomcat-6.0.35_xt"));
//		long d2=System.currentTimeMillis();
//		System.out.println((d2-d1)/1000);
//		deleteFile(new File("V:\\work\\code\\mytools\\redirect\\datas\\customs\\xt3"));
		mapTo(new File("D:\\temp\\1.txt") ,new File("D:\\temp\\2.txt"));
	}
	/**
	 * 复制文件
	 * @param from
	 * @param to
	 */
	public static void copy(String from,String to) throws Exception{
		if(new File(from).getAbsolutePath().equals(new File(to).getAbsolutePath())){
			return;//同一个文件,不能写
		}
		if(new File(from).isDirectory()){
			copy(new File(from) ,new File(to));
			return;
		}
		mapTo(new File(from) ,new File(to));
	}
	public static void copy(File from ,File to){
		if(from.isDirectory()){
			to.mkdirs();
			File[] list=from.listFiles();
			for(File f:list){
				copy(f ,new File(to.getAbsolutePath()+File.separator+f.getName()));
			}
		}else if(from.isFile()){
//			mapTo(from,to);
			FileInputStream fin=null;
			FileOutputStream fout=null;
			try {
				fin = new FileInputStream( from );
				fout = new FileOutputStream( to );
				byte[]b=new byte[1024];
				int i=0;
				while((i=fin.read(b))!=-1){
					fout.write(b,0,i);
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				if(fin!=null){
					try {
						fin.close();
					} catch (Exception e) {}
				}
				if(fout!=null){
					try {
						fout.close();
					} catch (Exception e) {}
				}
			} 
		}
	}
	public static void mapTo(File from ,File to){
		FileInputStream fin=null;
		FileOutputStream fout=null;
		FileChannel fcin=null;
		FileChannel fcout=null;
		FileLock lock1=null;
		FileLock lock2=null;
		try {
			fin = new FileInputStream( from );
			fout = new FileOutputStream( to );
			fcin = fin.getChannel();
		    fcout = fout.getChannel();
		    lock2=  fcout.lock();
		    ByteBuffer buffer = ByteBuffer.allocate( 1024 );
		    while (true) {
		      buffer.clear();
		      int r = fcin.read( buffer );
		      if (r==-1) {
		        break;
		      }
		      buffer.flip();
		      fcout.write( buffer );
		    }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try{
				 lock2.release();
			}catch(Exception e){}
			if(fin!=null){
				try {
					fcin.close();
					fin.close();
				} catch (Exception e) {}
			}
			if(fout!=null){
				try {
					fcout.close();
					fout.close();
				} catch (Exception e) {}
			}
		} 
		    
	}
	/**
	 * 复制文件
	 * @param from
	 * @param to
	 */
	public static void copy(String from,OutputStream to) throws Exception{		
		FileInputStream in=null;
		try {
			in=new FileInputStream(from);
			write(in,to);
		} catch (Exception e) {
			throw e;
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {}
			}
		}
		
	}
	//把流写入文件
	public static void write(InputStream in,File toFile) throws Exception{
		if(!toFile.getParentFile().isDirectory()){
			toFile.getParentFile().mkdirs();
		}
		FileOutputStream fos=null;
		try {
			fos=new FileOutputStream(toFile);
			byte [] b=new byte[1024];
			int i=0;
			while((i=in.read(b))!=-1){
				fos.write(b, 0, i);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw e;
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {}
			}
			if(fos!=null){
				try {
					fos.close();
				} catch (Exception e) {}
			}
		}
	}
	//把流写入文件
	public static void write(InputStream in,String to) throws Exception{
		write(in,new File(to));
	}
	//把流写入文件
	public static void write(InputStream in,OutputStream out) throws Exception{
		try {
			byte [] b=new byte[1024];
			int i=0;
			while((i=in.read(b))!=-1){
				out.write(b, 0, i);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw e;
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {}
			}
		}
	}
	public static long getFileSize(File file){
		if(file.isFile()){
			return file.length();
		}else if(file.isDirectory()){
			long len=0L;
			for(File f:file.listFiles()){
				len+=getFileSize(f);
			}
			return len;
		}
		return 0L;
	}
	public static void deleteFile(File file){
		List<File> list=getAllFile(file);
		for(File f:list){
			f.delete();
		}
	}
	public static List<File>  getAllFile(File f){
		List<File> list=new ArrayList<File> ();
		if(f.isDirectory()){
			File[] fs=f.listFiles();
			for(File inf:fs){
				list.addAll(getAllFile(inf));
			}
		}
		list.add(f);
		return list;
	}
}